package com.wb3.meta.common.utils;


import org.apache.commons.codec.binary.Base64;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URLEncoder;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class StringCommonUtils {
    private static Pattern linePattern = Pattern.compile("_([a-z])");

    private static Pattern humpPattern = Pattern.compile("\\B(\\p{Upper})(\\p{Lower}*)");
    /**
     * 下划线转驼峰
     * user_name  ---->  userName
     * userName   --->  userName
     *
     * @param underlineStr 带有下划线的字符串
     * @return 驼峰字符串
     */
    public static String toCamelCase(String underlineStr) {
        Matcher matcher = linePattern.matcher(underlineStr);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
    /**
     * @Author RP
     * @Description //移除括号 及其内部文字，
     * @Date 16:51 2024/1/21
     * @Param [input]
     * @return java.lang.String
     **/
    public static String removeBrackets(String input) {
        // 定义正则表达式匹配全角和半角括号及其内部内容
        String regex = "[（(][^）)]*[）)]";

        // 编译正则表达式
        Pattern pattern = Pattern.compile(regex);

        // 创建匹配器
        Matcher matcher = pattern.matcher(input);

        // 使用 replaceAll 方法替换匹配到的括号及其内部内容
        String result = matcher.replaceAll("");

        return result;
    }

    /**
     *   只允许字母和数字 // String regEx ="[^a-zA-Z0-9]";
     *   清除掉所有特殊字符
     * */
    public static String StringFilter(String str) throws UnsupportedEncodingException {
        str = URLEncoder.encode(str,"UTF-8");
        String regEx="[^0-9a-zA-Z\\u4E00-\\u9FA5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * 驼峰转 下划线
     * userName  ---->  user_name
     * user_name  ---->  user_name
     *
     * @param camelCaseStr 驼峰字符串
     * @return 带下滑线的String
     */
    public static String toUnderlineCase(String camelCaseStr) {
        if (camelCaseStr == null) {
            return null;
        }
        // 将驼峰字符串转换成数组
        char[] charArray = camelCaseStr.toCharArray();
        StringBuffer buffer = new StringBuffer();
        //处理字符串
        for (int i = 0, l = charArray.length; i < l; i++) {
            if (charArray[i] >= 65 && charArray[i] <= 90) {
                buffer.append("_").append(charArray[i] += 32);
            } else {
                buffer.append(charArray[i]);
            }
        }
        return buffer.toString();
    }

    /**
     * @Author raopeng
     * @Description //TODO 获取随机字母
     * @Date 2021/8/2 17:59
     * @Param [num]
     * @return java.lang.String
     **/
    public static String getRandStr(int num){

        String strs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        StringBuffer buff = new StringBuffer();

        for(int i=1;i<=num;i++){

            char str = strs.charAt((int)(Math.random() * 26));

            buff.append(str);

        }
        return buff.toString();
    }

    /**
     *
     * 登录token生成
     * */
    public static String generateToken(int length) {
        StringBuilder sb = new StringBuilder();
        Random random = new Random();
        int len = "abcdefghijklmnopqrstuvwxyz0123456789".length();

        for(int i = 0; i < length; ++i) {
            sb.append("abcdefghijklmnopqrstuvwxyz0123456789".charAt(random.nextInt(len - 1)));
        }

        return sb.toString();
    }

    /**
     * 生成UUID
     * @return
     */
    public static String GetUUID() {
        return UUID.randomUUID().toString().replace("-", "");
    }
    public static String generateUniqueCode() {
        UUID uuid = UUID.randomUUID();
        return uuid.toString().replaceAll("-", "").substring(0, 10);
    }

    /**
     * 是否为空数据
     * @param info
     * @return
     */
    public static boolean isEmpty(String info) {
        if (info == null) {
            return true;
        }
        return info.isEmpty();
    }

    /**
     * 生成sign
     * @return
     */
    public static String generateCPSign(Map<String,Object> requestParams, final String cpAuthKey)
    {
        // 对消息体中查询字符串按字典序排序并且进行URLCode编码        |  Sort the request parameters in the message body based on the ASCII codes of their names and URL encode the parameter values.
        String baseStr = format(requestParams, cpAuthKey);
        // 用CP侧签名私钥对上述编码后的请求字符串进行签名      |  Sign the encoded request parameter string using the CP-side signature generation private key.
//        String cpSign = sign(baseStr.getBytes(Charset.forName("UTF-8")), cpAuthKey);
        //MD5加密,结果转换为大写字符
        String sign = encodeByMD5(baseStr).toUpperCase();
        return sign;
    }

    /**
     * 根据参数Map构造排序好的参数串        | Construct a string of sorted parameters based on the parameter map.
     *
     * @param params
     * @return
     */
    private static String format(Map<String, Object> params, String key)
    {
        StringBuffer base = new StringBuffer();
        Map<String, Object> tempMap = new TreeMap<String, Object>(params);
        // 获取计算nsp_key的基础串        | Obtain the base string for calculating nsp_key.
        try
        {
            for (Map.Entry<String, Object> entry : tempMap.entrySet())
            {
                String k = entry.getKey();
                String v = String.valueOf(entry.getValue());
                base.append(k).append("=").append(URLEncoder.encode(v, "UTF-8")).append("&");
            }
        }
        catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }
        base = base.append("key=" + key);
        String body = base.toString().substring(0, base.toString().length() - 1);

        // 空格和星号转义      | Escape spaces and asterisks (*).
        body = body.replaceAll("\\+", "%20").replaceAll("\\*", "%2A");
        return body;
    }


    /**
     * 对字符串进行MD5加密
     *
     * @param str 需要加密的字符串
     * @return 小写MD5字符串 32位
     */
    public static String encodeByMD5(String str) {
        MessageDigest digest;

        try {
            digest = MessageDigest.getInstance("MD5");
            digest.update(str.getBytes());
            return new BigInteger(1, digest.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }


    private static String sign(byte[] data, String privateKey)
    {
        try
        {
            byte[] e = Base64.decodeBase64(privateKey);
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(e);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateK);
            signature.update(data);
            String signs = Base64.encodeBase64String(signature.sign());
            return signs;

        }
        catch (Exception var)
        {
            var.printStackTrace();
            return "";
        }
    }

    /**
     * 方法：字符串按字节固定长度分割数组
     * startPos 子串在原字符串字节数组的开始截取下标
     * startStrPos 子串在原字符串开始截取的下标
     * strLen 原字符串字节数组长度
     * 背景：由于编码格式不同，直接截取可能会拿到一个被砍一半的乱码，如utf-8 4byte 一个中文，如果截取的时候是5byte，就会出现乱码
     * 原理：1、先按字节数组进行截取，获得一个长度不大于固定截取长度的字节数组
     *      2、把字节数组转字符串得到一个新子串，再转byte数组后，两数组长度进行比较（新子串再转byte数组时，会对截取了一半的字符进行补全为对应编码集一个字符的长度），
     *         如果新子串的字节数组比按长度截取的子串字节数组长，说明存在截取一半的字符，这个字符会在最后一个位置，要舍弃
     *         所以，新子串按字符串长度截取减少1位，得到的字符串就是没有截取一半的字符，且长度小于等于需要的字节长度的子串。
     *
     * 1.当 子串字节数组开始截取下标 小于 原字符串字节数组长度 一直循环
     * 2.子串字节数组大小 需要根据 当前父串字节数组的截取下标和长度差值 与 预想截取的字节长度 比较来创建（否则用System.arraycopy会报错）
     * 3.根据 子串在原字符串字节数组的开始截取下标 拷贝父字节数组的内容到子字节数组
     * 4.根据 子串在原字符串开始截取的下标 与 子字节数组转为字符串的长度 在父字符串截取一个伪子串（可能最后一个字符被截取一半是乱码）
     * 5.比较伪子串转字节数组后长度 与 预想截取的字节数组长度，大于，则伪子串截取字符串长度-1
     * 6.子串字节数组开始截取下标 + 得到的子串字节长度；子串在原字符串开始截取的下标 + 得到子串的字符长度
     * @param str 原字符串
     * @param len 分割字串字节长度
     * @return List<String> 分割后的子串
     * @throws UnsupportedEncodingException
     */
    public static final List<String> divideStrByBytes(String str, int len) throws UnsupportedEncodingException{
        String charSet = "UTF-8";
        List<String> strSection = new ArrayList<>();
        byte[] bt = str.getBytes(charSet);
        int strLen = bt.length;
        int startPos = 0;
        int startStrPos = 0;
        while (startPos < strLen) {
            Integer subSectionLen = len;
            if (strLen - startPos < len) {
                subSectionLen = strLen - startPos;
            }
            byte[] br = new byte[subSectionLen];
            System.arraycopy(bt, startPos, br, 0, subSectionLen);
            String res = new String(br, charSet);
            int resLen = res.length();
            if (str.substring(startStrPos, startStrPos + resLen).getBytes(charSet).length > len) {
                res = res.substring(0, resLen - 1);
            }
            startStrPos += res.length();
            strSection.add(res);
            startPos += res.getBytes(charSet).length;
        }
        return strSection;
    }


}
